<template>
  <div :class="[
    'crud-input',
    `crud-input--${size}`,
    {
      'crud-input--disabled': disabled,
      'crud-input--readonly': readonly,
      'crud-input--clearable': clearable && modelValue,
      'crud-input--with-prefix': $slots.prefix || prefixIcon,
      'crud-input--with-suffix': $slots.suffix || suffixIcon || clearable,
      'crud-input--focused': isFocused
    }
  ]">
    <!-- 前缀图标 -->
    <div v-if="$slots.prefix || prefixIcon" class="crud-input__prefix">
      <slot name="prefix">
        <el-icon v-if="prefixIcon" class="crud-input__icon">
          <component :is="prefixIcon" />
        </el-icon>
      </slot>
    </div>

    <!-- 输入框 -->
    <el-input ref="inputRef" v-model="inputValue" :type="type" :placeholder="placeholder" :disabled="disabled"
      :readonly="readonly" :maxlength="maxlength" :minlength="minlength" :show-word-limit="showWordLimit"
      :show-password="showPassword" :clearable="false" :size="size" :autocomplete="autocomplete" :name="name"
      :form="form" :label="label" :tabindex="tabindex" :validate-event="validateEvent" class="crud-input__inner"
      @input="handleInput" @change="handleChange" @focus="handleFocus" @blur="handleBlur" @clear="handleClear"
      @keydown="handleKeydown" @keyup="handleKeyup" v-bind="$attrs" />

    <!-- 后缀图标 -->
    <div v-if="$slots.suffix || suffixIcon || clearable" class="crud-input__suffix">
      <!-- 清除按钮 -->
      <el-icon v-if="clearable && modelValue && !disabled && !readonly" class="crud-input__clear" @click="handleClear">
        <CircleClose />
      </el-icon>

      <slot name="suffix">
        <el-icon v-if="suffixIcon" class="crud-input__icon">
          <component :is="suffixIcon" />
        </el-icon>
      </slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, nextTick } from 'vue'
import { ElInput, ElIcon } from 'element-plus'
import { CircleClose } from '@element-plus/icons-vue'
import type { Component } from 'vue'

/**
 * 输入框组件属性接口
 */
interface Props {
  /** 绑定值 */
  modelValue?: string | number
  /** 输入框类型 */
  type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url'
  /** 是否展示密码切换按钮（仅在 type=password 时生效） */
  showPassword?: boolean
  /** 占位符文本 */
  placeholder?: string
  /** 是否禁用 */
  disabled?: boolean
  /** 是否只读 */
  readonly?: boolean
  /** 最大输入长度 */
  maxlength?: number
  /** 最小输入长度 */
  minlength?: number
  /** 是否显示字数统计 */
  showWordLimit?: boolean
  /** 是否可清空 */
  clearable?: boolean
  /** 输入框尺寸 */
  size?: 'large' | 'default' | 'small'
  /** 前缀图标 */
  prefixIcon?: Component
  /** 后缀图标 */
  suffixIcon?: Component
  /** 自动完成 */
  autocomplete?: 'on' | 'off'
  /** 原生name属性 */
  name?: string
  /** 原生form属性 */
  form?: string
  /** 标签文本 */
  label?: string
  /** 原生tabindex属性 */
  tabindex?: string | number
  /** 是否触发表单验证 */
  validateEvent?: boolean
}

/**
 * 组件事件接口
 */
interface Emits {
  /** 更新绑定值 */
  (e: 'update:modelValue', value: string | number): void
  /** 输入事件 */
  (e: 'input', value: string | number): void
  /** 值改变事件 */
  (e: 'change', value: string | number): void
  /** 获得焦点事件 */
  (e: 'focus', event: FocusEvent): void
  /** 失去焦点事件 */
  (e: 'blur', event: FocusEvent): void
  /** 清空事件 */
  (e: 'clear'): void
  /** 键盘按下事件 */
  (e: 'keydown', event: KeyboardEvent): void
  /** 键盘抬起事件 */
  (e: 'keyup', event: KeyboardEvent): void

}

// 定义组件属性，设置默认值
const props = withDefaults(defineProps<Props>(), {
  type: 'text',
  placeholder: '',
  disabled: false,
  readonly: false,
  showWordLimit: false,
  showPassword: false,
  clearable: false,
  size: 'default',
  autocomplete: 'off',
  validateEvent: true
})

// 定义组件事件
const emit = defineEmits<Emits>()

// 输入框引用
const inputRef = ref<InstanceType<typeof ElInput>>()

// 焦点状态
const isFocused = ref(false)

// 计算属性：输入框值
const inputValue = computed({
  get: () => props.modelValue ?? '',
  set: (value: string | number) => {
    emit('update:modelValue', value)
  }
})

/**
 * 处理输入事件
 * @param value - 输入值
 */
const handleInput = (value: string | number): void => {
  emit('input', value)
}

/**
 * 处理值改变事件
 * @param value - 改变后的值
 */
const handleChange = (value: string | number): void => {
  emit('change', value)
}

/**
 * 处理获得焦点事件
 * @param event - 焦点事件
 */
const handleFocus = (event: FocusEvent): void => {
  isFocused.value = true
  emit('focus', event)
}

/**
 * 处理失去焦点事件
 * @param event - 焦点事件
 */
const handleBlur = (event: FocusEvent): void => {
  isFocused.value = false
  emit('blur', event)
}

/**
 * 处理清空事件
 */
const handleClear = (): void => {
  inputValue.value = ''
  emit('clear')
  nextTick(() => {
    inputRef.value?.focus()
  })
}

/**
 * 处理键盘按下事件
 * @param event - 键盘事件
 */
const handleKeydown = (event: Event | KeyboardEvent): void => {
  emit('keydown', event as KeyboardEvent)
}

/**
 * 处理键盘抬起事件
 * @param event - 键盘事件
 */
const handleKeyup = (event: Event | KeyboardEvent): void => {
  emit('keyup', event as KeyboardEvent)
}

/**
 * 获取焦点
 */
const focus = (): void => {
  inputRef.value?.focus()
}

/**
 * 失去焦点
 */
const blur = (): void => {
  inputRef.value?.blur()
}

/**
 * 选中输入框文本
 */
const select = (): void => {
  inputRef.value?.select()
}

/**
 * 重置输入框值
 */
const reset = (): void => {
  inputValue.value = ''
}

// 暴露方法给父组件
defineExpose({
  focus,
  blur,
  select,
  reset
})
</script>

<style lang="scss" scoped>
.crud-input {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 100%;
  border-radius: 6px;
  border: none; // 去除边框
  background-color: #f5f5f5; // 浅灰色背景
  font-weight: 500;
  // font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; // 与系统一致的字体
  transition: all 0.2s ease;

  &:hover:not(.crud-input--disabled) {
    background-color: #eeeeee; // 悬停时稍微深一点的灰色
  }

  &.crud-input--focused {
    background-color: #eeeeee; // 聚焦时稍微深一点的灰色
    box-shadow: none; // 去除聚焦时的边框阴影
  }

  // 尺寸样式
  &--large {
    height: 40px;

    .crud-input__prefix,
    .crud-input__suffix {
      padding: 0 12px;
    }

    .crud-input__icon {
      font-size: 18px;
    }
  }

  &--default {
    height: 32px;

    .crud-input__prefix,
    .crud-input__suffix {
      padding: 0 10px;
    }

    .crud-input__icon {
      font-size: 16px;
    }
  }

  &--small {
    height: 24px;

    .crud-input__prefix,
    .crud-input__suffix {
      padding: 0 8px;
    }

    .crud-input__icon {
      font-size: 14px;
    }
  }

  // 状态样式
  &--disabled {
    background-color: $bg-color-gray;
    border-color: $border-color-lighter;
    cursor: not-allowed;

    .crud-input__prefix,
    .crud-input__suffix {
      color: $text-color-disabled;
    }
  }

  &--readonly {
    background-color: $bg-color-gray;
    cursor: default;
  }

  // 前缀样式
  &__prefix {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #666666; // 深灰色
    background-color: transparent; // 透明背景
    border-right: none;
    border-radius: 6px 0 0 6px;
    flex-shrink: 0;
  }

  // 后缀样式
  &__suffix {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #666666; // 深灰色
    flex-shrink: 0;
    gap: 4px;
  }

  // 图标样式
  &__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    color: #666666; // 深灰色
    transition: color 0.2s ease;
  }

  // 清除按钮样式
  &__clear {
    cursor: pointer;
    color: #666666; // 深灰色
    transition: color 0.2s ease;

    &:hover {
      color: #333333; // 悬停时更深的灰色
    }
  }

  // 输入框内部样式
  &__inner {
    flex: 1;
    border: none;

    :deep(.el-input__wrapper) {
      border: none;
      box-shadow: none;
      background-color: transparent;
      padding: 0 12px;

      &.is-focus {
        box-shadow: none;
      }
    }

    :deep(.el-input__inner) {
      border: none;
      background-color: transparent;
      color: #666666; // 深灰色文字
      font-family: inherit; // 继承父元素的字体设置

      &::placeholder {
        color: #999999; // 占位符文字稍浅一些的灰色
        font-family: inherit; // 继承父元素的字体设置
      }
    }
  }

  // 有前缀时的样式调整
  &--with-prefix {
    .crud-input__inner {
      :deep(.el-input__wrapper) {
        padding-left: 0;
        border-radius: 0 6px 6px 0;
      }
    }
  }

  // 有后缀时的样式调整
  &--with-suffix {
    .crud-input__inner {
      :deep(.el-input__wrapper) {
        padding-right: 0;
      }
    }
  }
}

// 深色模式适配
@media (prefers-color-scheme: dark) {
  .crud-input {
    background-color: $bg-color-card-dark;
    border-color: $border-color-base-dark;

    &:hover:not(.crud-input--disabled) {
      border-color: $primary-color-light;
    }

    &--disabled {
      background-color: $bg-color-gray-dark;
      border-color: $border-color-lighter-dark;
    }

    &--readonly {
      background-color: $bg-color-gray-dark;
    }

    &__prefix {
      background-color: $bg-color-gray-dark;
      color: $text-color-muted-dark;
    }

    &__suffix {
      color: $text-color-muted-dark;
    }

    &__icon {
      color: $text-color-muted-dark;
    }

    &__clear {
      color: $text-color-muted-dark;

      &:hover {
        color: $text-color-primary-dark;
      }
    }

    &__inner {
      :deep(.el-input__inner) {
        color: $text-color-primary-dark;

        &::placeholder {
          color: $text-color-muted-dark;
        }
      }
    }
  }
}
</style>
